#
# Execution helpers for os commands
#

implement Os;
include "sys.m";
	sys: Sys;
	Dir, pctl, NEWPGRP, DMDIR, open, OREAD, FD, OWRITE, ORCLOSE, FORKFD,
	ORDWR, FORKNS, NEWFD, MREPL, MBEFORE, MAFTER, MCREATE, pipe, mount,
	fprint, sprint, create, pwrite, read, QTDIR, QTFILE, fildes, Qid: import sys;
include "error.m";
	err: Error;
	checkload, stderr, panic, kill, error: import err;
include "env.m";
	env: Env;
	getenv: import env;
include "string.m";
	str: String;
	splitl, splitstrr : import str;
include "names.m";
	names: Names;
	cleanname, rooted: import names;
include "workdir.m";
	wdir: Workdir;
include "os.m";

emuroot: string;

init()
{
	sys = load Sys Sys->PATH;
	err = load Error Error->PATH;
	err->init();
	str = checkload(load String String->PATH, String->PATH);
	env = checkload(load Env Env->PATH, Env->PATH);
	names = checkload(load Names Names->PATH, Names->PATH);
	wdir = checkload(load Workdir Workdir->PATH, Workdir->PATH);
	host = getenv("emuhost");
}

filename(name: string): string
{
	if (emuroot == nil)
		emuroot = getenv("emuroot");
	if (emuroot == nil)
		emuroot = "/usr/inferno";
	name = cleanname(name);
	name = rooted(wdir->init(), name);
	return emuroot + name;
}

readall(fd: ref FD) : string
{
	if (fd == nil)
		return "";
	max : con int 8192;
	data := array[max] of byte;
	tot := nr := 0;
	do {
		nr = read(fd, data[tot:], len data - tot);
		if (nr > 0)
			tot += nr;
	} while(nr > 0 && tot < len data);
	if (tot == 0)
		return "";
	return string data[0:tot];
	
}

run(cmd: string): (string, string)
{
	cfd := open("/cmd/clone", ORDWR);
	if (cfd == nil) 
		return (nil, sprint("cmd: clone: %r"));
	nam := array[40] of byte;
	nr := read(cfd, nam, len nam);
	if (nr == 0)
		return(nil, "cmd: ctl eof");
	if (nr < 0)
		return (nil, sprint("cmd: ctl: %r"));
	dir := "/cmd/" + string nam[0:nr];
	fd := open(dir + "/data", OREAD);
	fprint(cfd, "killonclose");
	fprint(cfd, "exec %s", cmd);
	out := readall(fd);
	return (out, nil);
}
